import 'package:cave_flutter/style/whl_style.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class LSLoveProgressView extends StatefulWidget {
  final double width;
  final double height;
  final double waveHeight;
  final Color color;
  final Color fillColor;
  final double strokeWidth;
  final double progress;
  final double factor;
  final int secondAlpha;

  const LSLoveProgressView({super.key,
    this.width = 100,
    this.height = 100 / 0.618,
    this.factor = 1,
    this.waveHeight = 5,
    this.progress = 0.5,
    this.color = Colors.green,
    this.fillColor = Colors.white,
    this.strokeWidth = 3,
    this.secondAlpha = 88,
  });

  @override
  _LSLoveProgressViewState createState() => _LSLoveProgressViewState();
}

class _LSLoveProgressViewState extends State<LSLoveProgressView>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation _anim;

  @override
  void initState() {
    _controller =
        AnimationController(vsync: this, duration: Duration(milliseconds: 3000))
          ..addListener(() {
            setState(() {});
          })
          ..repeat();
    _anim = CurveTween(curve: Curves.linear).animate(_controller);
    super.initState();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    _controller.stop();
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return UnconstrainedBox(
      child: Container(
        width: widget.width,
        height: widget.height,
        child: CustomPaint(
          painter: BezierPainter(
            factor: _anim.value,
            waveHeight: widget.waveHeight,
            progress: widget.progress,
            color: widget.color,
            fillColor: widget.fillColor,
            strokeWidth: widget.strokeWidth,
            secondAlpha: widget.secondAlpha,
          ),
        ),
      ),
    );
  }
}

class BezierPainter extends CustomPainter {
  late Paint _mainPaint;
  late Path _mainPath;

  double waveWidth = 80;
  double wrapHeight = 0;

  final double waveHeight;
  final Color color;
  final Color fillColor;
  TextStyle? style;
  String? title;
  final double strokeWidth;
  final double progress;
  final double factor;
  final int secondAlpha;
  final double borderRadius;
  final bool isOval;

  BezierPainter(
      {this.factor = 1,
      this.waveHeight = 8,
      this.progress = 0.5,
      this.color = Colors.green,
      this.fillColor = Colors.white,
      this.style,
      this.title,
      this.strokeWidth = 3,
      this.secondAlpha = 88,
      this.isOval = false,
      this.borderRadius = 20}) {
    _mainPaint = Paint()
      ..color = Colors.yellow
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2;
    _mainPath = Path();
  }

  @override
  void paint(Canvas canvas, Size size) {

    final Paint body = Paint();
    body
      ..color = fillColor
      ..style = PaintingStyle.fill
      ..strokeWidth = 0;

    // The border of the heart
    final Paint border = Paint();
    border
      ..color = fillColor
      ..style = PaintingStyle.stroke
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 1;

    final double width = size.width;
    final double height = size.height;

    final Path path = Path();
    path.moveTo(0.5 * width, height * 0.4);
    path.cubicTo(0.2 * width, 0, -0.25 * width, height * 0.6,
        0.5 * width, height);
    path.moveTo(0.5 * width, height * 0.4);
    path.cubicTo(0.8 * width, 0, 1.25 * width, height * 0.6,
        0.5 * width, height);

    canvas.drawPath(path, body);
    canvas.drawPath(path, border);

    canvas.clipPath(path);

    waveWidth = size.width / 2;
    wrapHeight = size.height;

    canvas.translate(0, wrapHeight);
    canvas.save();
    canvas.translate(0, waveHeight);
    canvas.save();
    canvas.translate(-4 * waveWidth + 2 * waveWidth * factor, 0);
    drawWave(canvas);
    canvas.drawPath(
        _mainPath,
        _mainPaint
          ..style = PaintingStyle.fill
          ..color = color.withAlpha(88));
    canvas.restore();

    canvas.translate(-4 * waveWidth + 2 * waveWidth * factor * 2, 0);
    drawWave(canvas);
    canvas.drawPath(
        _mainPath,
        _mainPaint
          ..style = PaintingStyle.fill
          ..color = color);

    canvas.restore();

  }

  void drawWave(Canvas canvas) {
    _mainPath.moveTo(0, 0);
    _mainPath.relativeLineTo(0, -wrapHeight*0.8 * progress);
    _mainPath.relativeQuadraticBezierTo(
        waveWidth / 2, -waveHeight * 2, waveWidth, 0);
    _mainPath.relativeQuadraticBezierTo(
        waveWidth / 2, waveHeight * 2, waveWidth, 0);
    _mainPath.relativeQuadraticBezierTo(
        waveWidth / 2, -waveHeight * 2, waveWidth, 0);
    _mainPath.relativeQuadraticBezierTo(
        waveWidth / 2, waveHeight * 2, waveWidth, 0);
    _mainPath.relativeQuadraticBezierTo(
        waveWidth / 2, -waveHeight * 2, waveWidth, 0);
    _mainPath.relativeQuadraticBezierTo(
        waveWidth / 2, waveHeight * 2, waveWidth, 0);
    _mainPath.relativeLineTo(0, wrapHeight);
    _mainPath.relativeLineTo(-waveWidth * 3 * 2.0, 0);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}
